//
//  LocationDetailsViewController.swift
//  MyLocations
//
//  Created by cygarm on 15/12/8.
//  Copyright © 2015年 cygarm. All rights reserved.
//

import UIKit
import CoreLocation
import CoreData

private let dateFormatter: NSDateFormatter = {
	let formatter = NSDateFormatter()
	formatter.dateStyle = .MediumStyle
	formatter.timeStyle = .ShortStyle
	return formatter
}()

class LocationDetailsViewController: UITableViewController {
	@IBOutlet weak var descriptionTextView: UITextView!
	@IBOutlet weak var categoryLabel: UILabel!
	@IBOutlet weak var latitudeLabel: UILabel!
	@IBOutlet weak var longitudeLabel: UILabel!
	@IBOutlet weak var addressLabel: UILabel!
	@IBOutlet weak var dateLabel: UILabel!
	@IBOutlet weak var imageView: UIImageView!
	@IBOutlet weak var addPhotoLabel: UILabel!
	
	var image: UIImage? {
		didSet {
			if let image = image {
				showImage(image)
			}
		}
	}
	
	var coordinate = CLLocationCoordinate2D(latitude: 0, longitude: 0)
	var placemark: CLPlacemark?
	var descriptionText = ""
	var categoryName = ""
	
	var managedObjectContext: NSManagedObjectContext!
	var date = NSDate()
	
	/// adding or editing mode,adding mode = nil
	var locationToEdit: Location? {
		didSet {
			if let location = locationToEdit {
				descriptionText = location.locationDescription
				categoryName = location.category
				date = location.date
				coordinate = CLLocationCoordinate2DMake(location.latitude, location.longitude)
				placemark = location.placemark
			}
		}
	}

	var observer: AnyObject!
	
	//MARK: App Lifecycle
	override func viewDidLoad() {
		super.viewDidLoad()
		
		listenForBackgroundNotification()
		
		//UI config
		tableView.backgroundColor = UIColor.blackColor()
		tableView.separatorColor = UIColor(white: 1.0, alpha: 0.2)
		tableView.indicatorStyle = .White
		
		descriptionTextView.textColor = UIColor.whiteColor()
		descriptionTextView.backgroundColor = UIColor.blackColor()
		
		addPhotoLabel.textColor = UIColor.whiteColor()
		addPhotoLabel.highlightedTextColor = addPhotoLabel.textColor
		
		addressLabel.textColor = UIColor(white: 1.0, alpha: 0.4)
		addressLabel.highlightedTextColor = addressLabel.textColor
		
		if let location = locationToEdit {
			title = "Edit Location"
			if location.hasPhoto {
				if let image = location.photoImage {
					showImage(image)
				}
			}
		}
		
		descriptionTextView.text = descriptionText
		categoryLabel.text = categoryName
		
		latitudeLabel.text = String(format: "%.8f", coordinate.latitude)
		longitudeLabel.text = String(format: "%.8f", coordinate.longitude)
		
		if let placemark = placemark {
			addressLabel.text = stringFromPlacemark(placemark)
		} else {
			addressLabel.text = "No Address Found"
		}
		
		dateLabel.text = formatDate(date)
		
		let gestureRecognizer = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard:"))
		gestureRecognizer.cancelsTouchesInView = false
		tableView.addGestureRecognizer(gestureRecognizer)
	}
	
	deinit {
		print("*** deinit \(self)")
		NSNotificationCenter.defaultCenter().removeObserver(observer)
	}
	
	override func viewWillLayoutSubviews() {
		super.viewWillLayoutSubviews()
		
		descriptionTextView.frame.size.width = view.frame.size.width - 30
	}
	
	func listenForBackgroundNotification() {
		observer = NSNotificationCenter.defaultCenter().addObserverForName(UIApplicationDidEnterBackgroundNotification, object: nil, queue: NSOperationQueue.mainQueue()) { [weak self] notification -> Void in
			if let strongSelf = self {
				if strongSelf.presentedViewController != nil {
					strongSelf.dismissViewControllerAnimated(false, completion: nil)
				}
			
				strongSelf.descriptionTextView.resignFirstResponder()
			}
		}
	}
	
	//MARK: UITableViewDelegate
	override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
		switch (indexPath.section, indexPath.row) {
		case (0, 0):
			return 88
		case (1, _):
			return imageView.hidden ? 44 : imageView.frame.height
		case (2, 2):
			addressLabel.frame.size = CGSize(width: view.bounds.size.width - 115, height: 10000)
			addressLabel.sizeToFit()
			addressLabel.frame.origin.x = view.bounds.size.width - addressLabel.frame.size.width - 15
			return addressLabel.frame.size.height + 20
		default:
			return 44
		}
	}
	
	override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
		if indexPath.section == 0 || indexPath.section == 1 {
			return indexPath
		} else {
			return nil
		}
	}
	
	override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
		if indexPath.section == 0 && indexPath.row == 0 {
			descriptionTextView.becomeFirstResponder()
		} else if indexPath.section == 1 && indexPath.row == 0 {
			tableView.deselectRowAtIndexPath(indexPath, animated: true)
			/*
			simulator无法模拟camera,会导致crash
			*/
			pickPhoto()
		}
	}
	
	override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
		cell.backgroundColor = UIColor.blackColor()
		
		if let textLable = cell.textLabel {
			textLable.textColor = UIColor.whiteColor()
			textLable.highlightedTextColor = textLable.textColor
		}
		
		if let detailLabel = cell.detailTextLabel {
			detailLabel.textColor = UIColor(white: 1.0, alpha: 0.4)
			detailLabel.highlightedTextColor = detailLabel.textColor
		}
		
		let selectionView = UIView(frame: CGRect.zero)
		selectionView.backgroundColor = UIColor(white: 1.0, alpha: 0.2)
		cell.selectedBackgroundView = selectionView
	}
	
	//MARK: IBAction
	@IBAction func done() {
		let hudView = HudView.hudInView(navigationController!.view, animated: true)
		
		var location: Location
		if let temp = locationToEdit {
			hudView.text = "Updated"
			location = temp
		} else {
			hudView.text = "Tagged"
			location = NSEntityDescription.insertNewObjectForEntityForName("Location", inManagedObjectContext: managedObjectContext) as! Location
			location.photoID = nil
		}
		location.locationDescription = descriptionText
		location.category = categoryName
		location.latitude = coordinate.latitude
		location.longitude = coordinate.longitude
		location.date = date
		location.placemark = placemark
		
		if let image = image {
			if !location.hasPhoto {
				location.photoID = Location.nextPhotoID()
			}
			let data = UIImageJPEGRepresentation(image, 0.5)
			do {
				try data?.writeToFile(location.photoPath, options: .DataWritingAtomic)
			} catch {
				print("Error writing file: \(error)")
			}
		}
		
		do {
			try managedObjectContext.save()
		} catch {
			fatalCoreDataError(error as NSError)
			return
		}
		
		afterDelay(0.6) { () -> () in
			self.dismissViewControllerAnimated(true, completion: nil)
		}
	}
	
	@IBAction func cancel() {
		dismissViewControllerAnimated(true, completion: nil)
	}
	
	@IBAction func categoryPickerDidPickCategory(segue: UIStoryboardSegue) {
		let controller = segue.sourceViewController as! CategoryPickerViewController
		categoryLabel.text = controller.selectedCategoryName
		categoryName = controller.selectedCategoryName
	}
	
	//MARK: Segue handle
	override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
		if segue.identifier == "SegueCategoryPicker" {
			let controller = segue.destinationViewController as! CategoryPickerViewController
			controller.selectedCategoryName = categoryName
		}
	}
	
	//MARK: helper method
	func stringFromPlacemark(placemark: CLPlacemark) -> String {
		return 
			"\(placemark.subThoroughfare ?? "") \(placemark.thoroughfare ?? ""), " +
			"\(placemark.locality ?? "") \(placemark.administrativeArea ?? "") " +
			"\(placemark.postalCode ?? "")" + "\(placemark.country ?? "")"
	}
	
	func formatDate(date: NSDate) -> String {
		return dateFormatter.stringFromDate(date)
	}
	
	func hideKeyboard(gestureRecognizer: UIGestureRecognizer) {
		let point = gestureRecognizer.locationInView(tableView)
		let indexPath = tableView.indexPathForRowAtPoint(point)
		
		if indexPath != nil && indexPath!.section == 0 && indexPath!.row == 0 {
			return
		}
		descriptionTextView.resignFirstResponder()
	}
	
	func showImage(image: UIImage) {
		let ratio = image.size.width / image.size.height
		imageView.image = image
		imageView.hidden = false
		imageView.frame = CGRect(x: 10, y: 0, width: 260, height: (260 / ratio) + 20)
		addPhotoLabel.hidden = true
	}
}

extension LocationDetailsViewController: UITextViewDelegate {
	func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
		descriptionText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text)
		return true
	}
	
	func textViewDidEndEditing(textView: UITextView) {
		descriptionText = textView.text
	}
}

extension LocationDetailsViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
	func pickPhoto() {
		if UIImagePickerController.isSourceTypeAvailable(.Camera) {
			showPhotoMenu()
		} else {
			choosePhotoFromLibrary()
		}
	}

	func takePhotoWithCamera() {
		let imagePicker = MyImagePickerController()
		imagePicker.view.tintColor = view.tintColor
		imagePicker.sourceType = .Camera
		imagePicker.delegate = self
		imagePicker.allowsEditing = true
		presentViewController(imagePicker, animated: true, completion: nil)
	}
	
	func choosePhotoFromLibrary() {
		let imagePicker = MyImagePickerController()
		imagePicker.view.tintColor = view.tintColor
		imagePicker.sourceType = .PhotoLibrary
		imagePicker.delegate = self
		imagePicker.allowsEditing = true
		presentViewController(imagePicker, animated: true, completion: nil)
	}
	
	func showPhotoMenu() {
		let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)
		let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
		alertController.addAction(cancelAction)
		
		let tackPhotoAction = UIAlertAction(title: "Take Photo", style: .Default, handler: { _ in self.takePhotoWithCamera() })
		alertController.addAction(tackPhotoAction)
		
		let chooseFromLibraryAction = UIAlertAction(title: "Choose From Library", style: .Default, handler: { _ in self.choosePhotoFromLibrary() })
		alertController.addAction(chooseFromLibraryAction)
		
		presentViewController(alertController, animated: true, completion: nil)
	}
		
	func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
		image = info[UIImagePickerControllerEditedImage] as! UIImage?
		tableView.reloadData()
		
		dismissViewControllerAnimated(true, completion: nil)
	}
	
	func imagePickerControllerDidCancel(picker: UIImagePickerController) {
		dismissViewControllerAnimated(true, completion: nil)
	}
}